#ifndef CFG_H
#define	CFG_H

#include <stdint.h>

#include "../DynArray.h"
#include "BasicBlock.h"
#include "../List.h"

//Crappy forward declaration.
typedef struct TranslationUnit TranslationUnit;

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct CFGNode CFGNode;
    
//CFG Edge
//Edges interconnect nodes. The counter indicates how many times the target
//has been reached from the current node. There's no need for the head since it
//directly contains these edges in a dynamic array.
typedef struct CFGEdge{
    uint64_t Count;
    CFGNode* Target;
}CFGEdge;

CFGEdge* CFGE_New(CFGNode* TargetNode);

//CFG Node
//Each node in the CFG is a simple structure that points to a Translation Unit (BB or other CFG).
//It also holds CFG edges to other nodes.

typedef enum CFG_DFSColor{
    DFSC_WHITE,
    DFSC_GRAY,
    DFSC_BLACK
} CFG_DFSColor;

typedef struct CFGNode{
    TranslationUnit* Unit;
    __LinkedList* Edges;
    
    uint64_t Size;
    
    uint64_t EpochExecutionCount;      //How many times this Node has been executed in the current epoch?
    
    uint8_t _Visited;                  //Used in graph traversals
    uint8_t _VisitedSize;              //Used in graph traversals for determining node size (# of instructions)
    
    //Variables used during Tarjan's
    uint64_t TARJ_Index;
    uint64_t TARJ_LowIndex;
    uint64_t TARJ_HighestTransitionCount;
    
    //Variables meaningful for SCC analysis
    uint64_t SCC_Index;    
    uint64_t SCC_HighestTransitionCount;
    
    //Variables used during the modified Colored DFS search for cycles
    uint64_t CYC_Color;
    
    //List of nodes that point to the current node.
    __LinkedList* SourceNodes;
    
    __LinkedList* SCC_HotNodes;       //List of hot Nodes. Only meaningful
                                      //for SCC Heads.
}CFGNode;

CFGNode* CFGN_New(TranslationUnit* TU);
void     CFGN_AddEdge(CFGNode* CFGN, CFGEdge* Edge);
CFGEdge* CFGN_EdgeTo(CFGNode* CFGN, uint16_t Address);

//The Control Flow Graph Node Map
//A fast search structure that is able to retrieve nodes based on a 16-bit address.
//No public interface for this one, since it only should be accessed by the CFG.
typedef struct CFGNodeMap{
    uint16_t MapKey;
    CFGNode* Data;
    struct CFGNodeMap** Children;
}CFGNodeMap;

//Control Flow Graph. Has a List of Entry Points as well as a Node Map.
//Control Flow Graphs are identified by the initial address of the first translation unit added.
//The control flow graph is responsible for storing tracing information.
//It not only stores basic blocks, but also other CFGs as nodes (Translation Units). This may
//improve hot region algorithms later.
typedef struct ControlFlowGraph{
    uint16_t InitialAddress;
    CFGNodeMap* Nodes;
    __LinkedList* NodeList;
    uint32_t NumNodes;
}ControlFlowGraph;

ControlFlowGraph* CFG_New(void);
void              CFG_AddNode(ControlFlowGraph* CFG, CFGNode* Node);
void              CFG_AddBBNode(ControlFlowGraph* CFG, TranslationUnit* TU);
CFGNode*          CFG_SearchNode(ControlFlowGraph* CFG, uint16_t InitialAddress);
void              CFG_PrintCFG(ControlFlowGraph* CFG, char* DotFilename);
void              CFG_ResetCFGForTraversal(ControlFlowGraph* CFG);
void              CFG_Reset(ControlFlowGraph *CFG);
void              CFG_Fuse(ControlFlowGraph* CFG, __LinkedList* Nodes);
void              CFG_UpdateNodeSizes(ControlFlowGraph* CFG);

//Control Flow Graph Repository
//This data structure maps PC addresses to control flow graphs.

void CFGRInit(void);

void CFGRRefresh(ControlFlowGraph* CFG);

void CFGRNodeRefresh(ControlFlowGraph* CFG, CFGNode* Node);

ControlFlowGraph* CFGRSearch(uint16_t Address);

void CFGRAddressSet(ControlFlowGraph* CFG, uint16_t Address);

#ifdef	__cplusplus
}
#endif

#endif	/* CFG_H */

